package gui.utilitarias.filemanager;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;
import javax.microedition.io.file.FileSystemRegistry;
import javax.microedition.lcdui.*;

public class SelecionarArquivo extends List implements CommandListener {

    private final static String PROTOCOLO_ARQUIVO_PREFIXO = "file:///";
    private final static String TITULO_PADRAO = "Selecionar";
    private final static char CARACTERE_SEPARADOR = '/';
    //Tipo de Selecao
    private final static int DIRETORIOS = 0;
    private final static int ARQUIVOS = 1;
    private String[] filter = new String[0];
    private int selectionMode;
    //Comandos
    private final Command cmdAbrir;
    private final Command cmdSelecionar;
    private final Command cmdCancelar;
    //Icones
    private Image icone_pasta;
    private Image icone_arquivo;
    //Navegacao
    private String[] drives = null;
    private String currentDirectory;
    private String selectedFileName;
    //Call Back
    private SelecionaListener listener;

    public SelecionarArquivo() {
        super(TITULO_PADRAO, IMPLICIT);

        this.selectionMode = 0;

        currentDirectory = "";

        cmdAbrir = new Command("Abrir", Command.OK, 1);
        cmdSelecionar = new Command("Selecionar", Command.SCREEN, 3);
        cmdCancelar = new Command("Cancel", Command.CANCEL, 4);

        try {
            icone_pasta = Image.createImage("/gui/utilitarias/filemanager/pasta.png");
            icone_arquivo = Image.createImage("/gui/utilitarias/filemanager/arquivo.png");
        } catch (IOException ex) {
        }

        addCommand(cmdSelecionar);
        addCommand(cmdCancelar);

        setSelectCommand(cmdAbrir);

        setCommandListener(this);

        show();
    }

    private String[] getRoots() {

        if (!isFileManagerSupported()) {
            return new String[0];
        }

        Enumeration roots = FileSystemRegistry.listRoots();
        Vector temp = new Vector(1);

        // String root;

        while (roots.hasMoreElements()) {
            // root = (String) roots.nextElement();
            temp.addElement((String) roots.nextElement());
        }

        String[] ret = new String[temp.size()];
        temp.copyInto(ret);
        return ret;
    }

    private Vector getDirectoryListing(String directory) throws Exception {
        try {
            Vector tempVector;

            try {
                if (directory.equalsIgnoreCase("")) {
                    if (drives == null) {
                        drives = getRoots();
                        if (drives == null) {
                            return null;
                        }
                    }

                    tempVector = new Vector(1);

                    for (int i = 0; i < drives.length; i++) {
                        tempVector.addElement(drives[i]);
                    }

                    delete(0);
                } else {
                    FileConnection fileConnection = (FileConnection) Connector.open(PROTOCOLO_ARQUIVO_PREFIXO + directory, Connector.READ);

                    if (!fileConnection.exists()) {
                        throw new Exception("Falha ao abrir: " + PROTOCOLO_ARQUIVO_PREFIXO + directory);
                    }

                    tempVector = new Vector(1);

                    for (Enumeration enumer = fileConnection.list(); enumer.hasMoreElements();) {
                        tempVector.addElement((String) enumer.nextElement());
                    }

                    fileConnection.close();
                }
            } catch (Exception exception) {
                throw new Exception(exception.toString());
            }
            return tempVector;
        } catch (Exception e) {
            throw e;
        }
    }

    private void show() {
        new Thread(new Runnable() {

            public void run() {
                deleteAll();

                append("..", icone_pasta);

                Vector dir;

                try {
                    dir = getDirectoryListing(currentDirectory);
                } catch (Exception ex) {
                    dir = new Vector(1);
                }

                for (int i = 0; i < dir.size(); i++) {
                    String fname = (String) dir.elementAt(i);

                    if (isDirectory(fname)) {
                        append(fname, icone_pasta);
                        continue;
                    }

                    if (selectionMode == ARQUIVOS) {
                        if (accept(fname)) {
                            append(fname, icone_arquivo);
                        }
                    }
                }
            }
        }).start();
    }

    private boolean accept(String fname) {
        String nome = fname.toLowerCase();
        for (int i = 0; i < filter.length; i++) {
            if (nome.endsWith(filter[i].toLowerCase()) || filter[i].toLowerCase().equals("any")) {
                return true;
            }
        }
        return false;
    }

    private boolean isDirectory(String directory) {
        if (directory.charAt(directory.length() - 1) == CARACTERE_SEPARADOR) {
            return true;
        } else {
            return false;
        }

    }

    public void commandAction(Command c, Displayable d) {
        if (c == cmdAbrir) {
            Thread t = new Thread(new Runnable() {

                public void run() {
                    String selected = getString(getSelectedIndex());

                    if (selected.equals("..") && getSelectedIndex() == 0) {
                        int index = currentDirectory.lastIndexOf('/', currentDirectory.length() - 2);

                        if (index < 0) {
                            currentDirectory = "";
                        } else {
                            currentDirectory = currentDirectory.substring(0, index + 1);
                        }
                        show();
                    } else if (!isDirectory(selected)) {
                        String url = currentDirectory + selected;
                        listener.arquivoSelecionado(url);
                    } else {
                        currentDirectory += selected;
                        show();
                    }
                }
            });
            t.start();
        } else if (c == cmdSelecionar) {
            selectedFileName = getString(getSelectedIndex());

            if (selectionMode == DIRETORIOS && isDirectory(selectedFileName)) {
                String url = currentDirectory + selectedFileName;
                listener.arquivoSelecionado(url);
                return;
            }

            if (selectionMode == ARQUIVOS) {
                String url = currentDirectory + selectedFileName;

                if (isDirectory(selectedFileName)) {
                    currentDirectory = url;

                    if (isDirectory(selectedFileName)) {

                        Thread t = new Thread(new Runnable() {

                            public void run() {
                                show();
                            }
                        });
                        t.start();
                    }
                } else {
                    listener.arquivoSelecionado(url);
                }
            }

        } else if (c == cmdCancelar) {
            listener.cancela();
        }
    }

    public String getSelectedFileName() {
        return selectedFileName;
    }

    private boolean isFileManagerSupported() {
        if (System.getProperty("microedition.io.file.FileConnection.version") != null) {
            return true;
        }
        return false;
    }

    public void switchToFolder() {
        selectionMode = DIRETORIOS;
    }

    public void switchToFiles(String[] ext) {
        selectionMode = ARQUIVOS;

        if (ext == null) {
            this.filter = new String[0];
            return;
        }

        filter = new String[ext.length];

        System.arraycopy(ext, 0, filter, 0, ext.length);
    }

    public void setListener(SelecionaListener listener) {
        this.listener = listener;
    }
}
